use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use crate::instruction::instruction::Instruction;
use crate::vm_thread::{VMFrame, VMThread};
use crate::vm_val::{VMValByte, VMValEnum, VMValInteger, VMValShort};

pub struct bipush {
    pub val: i8,
}

impl Instruction for bipush {
    fn read_operands(&mut self, frame: Rc<RefCell<VMFrame>>) {
        self.val = i8::from_be_bytes([frame.deref().borrow_mut().read_u8()]);
    }

    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValByte {
            val: VMValByte { num: self.val as i8 }
        })
    }

    fn to_string(&self) -> String {
        String::from("bipush")
    }
}


pub struct sipush {
    pub val: i16,
}

impl Instruction for sipush {
    fn read_operands(&mut self, frame: Rc<RefCell<VMFrame>>) {
        let mut rw_frame = frame.deref().borrow_mut();
        self.val = i16::from_be_bytes([rw_frame.read_u8(), rw_frame.read_u8()]);
    }

    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValShort {
            val: VMValShort { num: self.val }
        })
    }

    fn to_string(&self) -> String {
        String::from("sipush")
    }
}